namespace DotNetNuke.Modules.Admin.ResourceInstaller
{
    using DotNetNuke.Common.Utilities;
    using DotNetNuke.Entities.Modules;
    using DotNetNuke.Entities.Modules.Definitions;
    using DotNetNuke.Entities.Portals;
    using DotNetNuke.Framework.Providers;
    using ICSharpCode.SharpZipLib.Zip;
    using Microsoft.VisualBasic.CompilerServices;
    using System;
    using System.Collections;
    using System.IO;
    using System.Text;
    using System.Text.RegularExpressions;

    /// -----------------------------------------------------------------------------
    /// <summary>
    /// The PaDnnInstallerBase is a base class for all PaDnnInstallers
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <history>
    /// [cnurse]	05/09/2005  documented
    /// </history>
    /// -----------------------------------------------------------------------------
    public class PaDnnInstallerBase : ResourceInstallerBase
    {
        private PaInstallInfo _installerInfo;
        private ArrayList _upgradeversions;

        public PaDnnInstallerBase(PaInstallInfo InstallerInfo)
        {
            this._installerInfo = InstallerInfo;
        }

        protected virtual bool BatchSql(PaFile sqlFile)
        {
            bool WasSuccessful = true;
            this.InstallerInfo.Log.StartJob(string.Format(base.SQL_BeginFile, sqlFile.Name));
            string strScript = "";
            switch (sqlFile.Encoding)
            {
                case PaTextEncoding.UTF7:
                    strScript = this.GetAsciiString(sqlFile.Buffer, Encoding.UTF7);
                    break;

                case PaTextEncoding.UTF8:
                    strScript = this.GetAsciiString(sqlFile.Buffer, Encoding.UTF8);
                    break;

                case PaTextEncoding.UTF16BigEndian:
                    strScript = this.GetAsciiString(sqlFile.Buffer, Encoding.BigEndianUnicode);
                    break;

                case PaTextEncoding.UTF16LittleEndian:
                    strScript = this.GetAsciiString(sqlFile.Buffer, Encoding.Unicode);
                    break;

                case PaTextEncoding.Unknown:
                    throw new Exception(string.Format(base.SQL_UnknownFile, sqlFile.Name));
            }
            if (strScript.StartsWith("?"))
            {
                strScript = strScript.Substring(1);
            }
            string strSQLExceptions = PortalSettings.ExecuteScript(strScript, false);
            if (strSQLExceptions != "")
            {
                this.InstallerInfo.Log.AddFailure(string.Format(base.SQL_Exceptions, "\r\n", strSQLExceptions));
                WasSuccessful = false;
            }
            this.InstallerInfo.Log.EndJob(string.Format(base.SQL_EndFile, sqlFile.Name));
            return WasSuccessful;
        }

        protected virtual void CreateBinFile(PaFile File)
        {
            string binFullFileName = Path.Combine(Path.Combine(this.InstallerInfo.SitePath, "bin"), File.Name);
            this.CreateFile(binFullFileName, File.Buffer);
            this.InstallerInfo.Log.AddInfo(base.FILE_Created + binFullFileName);
        }

        protected virtual void CreateDataProviderFile(PaFile file, PaFolder Folder)
        {
            string rootFolder = Path.Combine(this.InstallerInfo.SitePath, Path.Combine("DesktopModules", Folder.FolderName));
            string ProviderTypeFolder = Path.Combine(@"Providers\DataProviders", file.Extension);
            string ProviderFolder = Path.Combine(rootFolder, ProviderTypeFolder);
            if (!Directory.Exists(ProviderFolder))
            {
                Directory.CreateDirectory(ProviderFolder);
            }
            string FullFileName = Path.Combine(ProviderFolder, file.Name);
            this.CreateFile(FullFileName, file.Buffer);
            this.InstallerInfo.Log.AddInfo(base.FILE_Created + FullFileName);
        }

        protected void CreateFile(string FullFileName, byte[] Buffer)
        {
            if (File.Exists(FullFileName))
            {
                File.SetAttributes(FullFileName, FileAttributes.Normal);
            }
            FileStream fs = new FileStream(FullFileName, FileMode.Create, FileAccess.Write);
            fs.Write(Buffer, 0, Buffer.Length);
            fs.Close();
        }

        protected virtual void CreateFiles(PaFolder Folder)
        {
            IEnumerator refObjectHelperL0=null;
            this.InstallerInfo.Log.StartJob(base.FILES_Creating);
            try
            {
                refObjectHelperL0 = Folder.Files.GetEnumerator();
                while (refObjectHelperL0.MoveNext())
                {
                    PaFile file = (PaFile) refObjectHelperL0.Current;
                    switch (file.Type)
                    {
                        case PaFileType.Dll:
                            this.CreateBinFile(file);
                            goto Label_00AD;

                        case PaFileType.Sql:
                        case PaFileType.Ascx:
                        case PaFileType.Dnn:
                        case PaFileType.Other:
                            this.CreateModuleFile(file, Folder);
                            goto Label_00AD;

                        case PaFileType.DataProvider:
                            if (file.Name.ToLower().IndexOf("uninstall") == -1)
                            {
                                break;
                            }
                            this.CreateModuleFile(file, Folder);
                            goto Label_00AD;

                        default:
                            goto Label_00AD;
                    }
                    this.CreateDataProviderFile(file, Folder);
                Label_00AD:;
                }
            }
            finally
            {
                if (refObjectHelperL0 is IDisposable)
                {
                    (refObjectHelperL0 as IDisposable).Dispose();
                }
            }
            this.InstallerInfo.Log.EndJob(base.FILES_Created);
        }

        protected virtual void CreateModuleFile(PaFile File, PaFolder Folder)
        {
            string FolderName = Folder.FolderName.Trim(new char[] { '[' }).Trim(new char[] { ']' });
            string rootFolder = "";
            if (File.Path.ToLower().StartsWith("[app_code]"))
            {
                rootFolder = Path.Combine(this.InstallerInfo.SitePath, Path.Combine("App_Code", FolderName));
                if (File.Path.ToLower() == "[app_code]")
                {
                    File.Path = "";
                }
                else
                {
                    File.Path = File.Path.Substring(10);
                }
            }
            else
            {
                rootFolder = Path.Combine(this.InstallerInfo.SitePath, Path.Combine("DesktopModules", FolderName));
            }
            if (!Directory.Exists(rootFolder))
            {
                Directory.CreateDirectory(rootFolder);
            }
            if ((((Folder.ResourceFile != null) && File.Name.ToLower().Equals(Folder.ResourceFile.ToLower())) ? 1 : 0) != 0)
            {
                this.CreateResourceFile(File, rootFolder);
            }
            else
            {
                string fileFolder = Path.Combine(rootFolder, File.Path);
                if (!Directory.Exists(fileFolder))
                {
                    Directory.CreateDirectory(fileFolder);
                }
                string FullFileName = Path.Combine(fileFolder, File.Name);
                this.CreateFile(FullFileName, File.Buffer);
                this.InstallerInfo.Log.AddInfo(base.FILE_Created + FullFileName);
            }
        }

        protected virtual void CreateResourceFile(PaFile ResourceFile, string RootFolder)
        {
            this.InstallerInfo.Log.StartJob(base.FILES_Expanding);
            try
            {
                ZipInputStream objZipInputStream = new ZipInputStream(new MemoryStream(ResourceFile.Buffer));
                FileSystemUtils.UnzipResources(objZipInputStream, RootFolder);
            }
            catch (Exception exception1)
            {
                
                Exception ex = exception1;
                
            }
            this.InstallerInfo.Log.EndJob(base.FILES_CreatedResources);
        }

        protected virtual void ExecuteSql(PaFolder Folder)
        {
            IEnumerator refObjectHelperL0=null;
            IEnumerator refObjectHelperL1=null;
            this.InstallerInfo.Log.StartJob(base.SQL_Begin);
            ArrayList arrScriptFiles = new ArrayList();
            PaFile InstallScript = null;
            try
            {
                refObjectHelperL0 = Folder.Files.GetEnumerator();
                while (refObjectHelperL0.MoveNext())
                {
                    PaFile file = (PaFile) refObjectHelperL0.Current;
                    if (((((file.Type == PaFileType.Sql) || (((file.Type == PaFileType.DataProvider) & (file.Name.ToLower().IndexOf("uninstall") == -1)) & (file.Name.ToLower().IndexOf(".xml") == -1))) ? 1 : 0) != 0) && (ProviderConfiguration.GetProviderConfiguration("data").DefaultProvider.ToLower() == Path.GetExtension(file.Name.ToLower()).Substring(1)))
                    {
                        if (file.Name.ToLower().StartsWith("install."))
                        {
                            InstallScript = file;
                        }
                        else
                        {
                            arrScriptFiles.Add(file);
                        }
                    }
                }
            }
            finally
            {
                if (refObjectHelperL0 is IDisposable)
                {
                    (refObjectHelperL0 as IDisposable).Dispose();
                }
            }
            string strModuleVersion = "000000";
            DesktopModuleInfo objDesktopModule = this.GetDesktopModule(Folder);
            if (objDesktopModule != null)
            {
                strModuleVersion = objDesktopModule.Version.Replace(".", "");
            }
            if ((InstallScript != null) & (objDesktopModule == null))
            {
                this.InstallerInfo.Log.AddInfo(base.SQL_Executing + InstallScript.Name);
                this.BatchSql(InstallScript);
                string strInstallVersion = Path.GetFileNameWithoutExtension(InstallScript.Name).Replace(".", "").ToLower().Replace("install", "");
                if (strInstallVersion != "")
                {
                    strModuleVersion = strInstallVersion;
                }
                this.UpgradeVersions.Add(Regex.Replace(strModuleVersion, @"^(?<a>\d{2})(?<b>\d{2})(?<c>\d{2})$", "${a}.${b}.${c}"));
            }
            PaDataProviderComparer Comparer = new PaDataProviderComparer();
            arrScriptFiles.Sort(Comparer);
            try
            {
                refObjectHelperL1 = arrScriptFiles.GetEnumerator();
                while (refObjectHelperL1.MoveNext())
                {
                    PaFile scriptFile = (PaFile) refObjectHelperL1.Current;
                    if (Operators.CompareString(Path.GetFileNameWithoutExtension(scriptFile.Name).Replace(".", ""), strModuleVersion, false) > 0)
                    {
                        this.UpgradeVersions.Add(Path.GetFileNameWithoutExtension(scriptFile.Name));
                        this.InstallerInfo.Log.AddInfo(base.SQL_Executing + scriptFile.Name);
                        this.BatchSql(scriptFile);
                    }
                }
            }
            finally
            {
                if (refObjectHelperL1 is IDisposable)
                {
                    (refObjectHelperL1 as IDisposable).Dispose();
                }
            }
            this.InstallerInfo.Log.EndJob(base.SQL_End);
        }

        protected string GetAsciiString(byte[] Buffer, Encoding SourceEncoding)
        {
            Encoding TargetEncoding = Encoding.ASCII;
            byte[] asciiBytes = Encoding.Convert(SourceEncoding, TargetEncoding, Buffer);
            return Encoding.ASCII.GetString(asciiBytes);
        }

        protected virtual DesktopModuleInfo GetDesktopModule(PaFolder Folder)
        {
            DesktopModuleController objDesktopModules = new DesktopModuleController();
            return objDesktopModules.GetDesktopModuleByFriendlyName(Folder.FriendlyName);
        }

        protected virtual DesktopModuleInfo GetDesktopModuleSettings(DesktopModuleInfo objDesktopModule, PaFolder Folder)
        {
            objDesktopModule.FriendlyName = Folder.FriendlyName;
            objDesktopModule.FolderName = Folder.FolderName;
            objDesktopModule.ModuleName = Folder.ModuleName;
            objDesktopModule.Description = Folder.Description;
            objDesktopModule.Version = Folder.Version;
            objDesktopModule.IsPremium = false;
            objDesktopModule.IsAdmin = false;
            return objDesktopModule;
        }

        protected int GetModDefID(int TempModDefID, ArrayList Modules)
        {
            IEnumerator refObjectHelperL0=null;
            try
            {
                refObjectHelperL0 = Modules.GetEnumerator();
                while (refObjectHelperL0.MoveNext())
                {
                    ModuleDefinitionInfo MI = (ModuleDefinitionInfo) refObjectHelperL0.Current;
                    if (MI.TempModuleID == TempModDefID)
                    {
                        return MI.ModuleDefID;
                    }
                }
            }
            finally
            {
                if (refObjectHelperL0 is IDisposable)
                {
                    (refObjectHelperL0 as IDisposable).Dispose();
                }
            }
            return -1;
        }

        public virtual void Install(PaFolderCollection folders)
        {
            IEnumerator refObjectHelperL0=null;
            try
            {
                refObjectHelperL0 = folders.GetEnumerator();
                while (refObjectHelperL0.MoveNext())
                {
                    PaFolder folder = (PaFolder) refObjectHelperL0.Current;
                    if (this.ValidateVersion(folder))
                    {
                        this.ExecuteSql(folder);
                        this.CreateFiles(folder);
                        if (folder.Modules.Count > 0)
                        {
                            this.RegisterModules(folder, folder.Modules, folder.Controls);
                        }
                    }
                    else
                    {
                        this.InstallerInfo.Log.AddWarning(base.INSTALL_Aborted);
                    }
                }
            }
            finally
            {
                if (refObjectHelperL0 is IDisposable)
                {
                    (refObjectHelperL0 as IDisposable).Dispose();
                }
            }
        }

        protected virtual void RegisterModules(PaFolder Folder, ArrayList Modules, ArrayList Controls)
        {
            IEnumerator refObjectHelperL0=null;
            IEnumerator refObjectHelperL1=null;
            this.InstallerInfo.Log.StartJob(base.REGISTER_Module);
            DesktopModuleController objDesktopModules = new DesktopModuleController();
            DesktopModuleInfo objDesktopModule = this.GetDesktopModule(Folder);
            if (objDesktopModule == null)
            {
                objDesktopModule = new DesktopModuleInfo();
                objDesktopModule.DesktopModuleID = Null.NullInteger;
            }
            objDesktopModule = this.GetDesktopModuleSettings(objDesktopModule, Folder);
            if (Null.IsNull(objDesktopModule.DesktopModuleID))
            {
                objDesktopModule.DesktopModuleID = objDesktopModules.AddDesktopModule(objDesktopModule);
            }
            else
            {
                objDesktopModules.UpdateDesktopModule(objDesktopModule);
            }
            this.InstallerInfo.Log.AddInfo(base.REGISTER_Definition);
            ModuleDefinitionController objModuleDefinitons = new ModuleDefinitionController();
            try
            {
                refObjectHelperL0 = Modules.GetEnumerator();
                while (refObjectHelperL0.MoveNext())
                {
                    ModuleDefinitionInfo objModuleDefinition = (ModuleDefinitionInfo) refObjectHelperL0.Current;
                    ModuleDefinitionInfo objModuleDefinition2 = objModuleDefinitons.GetModuleDefinitionByName(objDesktopModule.DesktopModuleID, objModuleDefinition.FriendlyName);
                    if (objModuleDefinition2 == null)
                    {
                        objModuleDefinition.DesktopModuleID = objDesktopModule.DesktopModuleID;
                        objModuleDefinition.ModuleDefID = objModuleDefinitons.AddModuleDefinition(objModuleDefinition);
                    }
                    else
                    {
                        objModuleDefinition.ModuleDefID = objModuleDefinition2.ModuleDefID;
                    }
                }
            }
            finally
            {
                if (refObjectHelperL0 is IDisposable)
                {
                    (refObjectHelperL0 as IDisposable).Dispose();
                }
            }
            this.InstallerInfo.Log.AddInfo(base.REGISTER_Controls);
            ModuleControlController objModuleControls = new ModuleControlController();
            try
            {
                refObjectHelperL1 = Controls.GetEnumerator();
                while (refObjectHelperL1.MoveNext())
                {
                    ModuleControlInfo objModuleControl = (ModuleControlInfo) refObjectHelperL1.Current;
                    objModuleControl.ModuleDefID = this.GetModDefID(objModuleControl.ModuleDefID, Modules);
                    ModuleControlInfo objModuleControl2 = objModuleControls.GetModuleControlByKeyAndSrc(objModuleControl.ModuleDefID, objModuleControl.ControlKey, objModuleControl.ControlSrc);
                    if (objModuleControl2 == null)
                    {
                        objModuleControls.AddModuleControl(objModuleControl);
                    }
                    else
                    {
                        objModuleControl.ModuleControlID = objModuleControl2.ModuleControlID;
                        objModuleControls.UpdateModuleControl(objModuleControl);
                    }
                }
            }
            finally
            {
                if (refObjectHelperL1 is IDisposable)
                {
                    (refObjectHelperL1 as IDisposable).Dispose();
                }
            }
            this.InstallerInfo.Log.EndJob(base.REGISTER_End);
            string UpgradeResults = this.UpgradeModule(objDesktopModule);
            if (UpgradeResults != null)
            {
                this.InstallerInfo.Log.AddInfo(UpgradeResults);
            }
        }

        protected virtual string UpgradeModule(DesktopModuleInfo ModuleInfo)
        {
            return null;
        }

        protected bool ValidateVersion(PaFolder Folder)
        {
            DesktopModuleInfo objDesktopModule = this.GetDesktopModule(Folder);
            if ((objDesktopModule != null) && (Operators.CompareString(objDesktopModule.Version, Folder.Version, false) > 0))
            {
                return false;
            }
            return true;
        }

        public PaInstallInfo InstallerInfo
        {
            get
            {
                return this._installerInfo;
            }
        }

        public ArrayList UpgradeVersions
        {
            get
            {
                if (this._upgradeversions == null)
                {
                    this._upgradeversions = new ArrayList();
                }
                return this._upgradeversions;
            }
            set
            {
                this._upgradeversions = value;
            }
        }
    }
}

